package com.wsh.sys.impl;

import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wsh.dto.sys.UserDto;
import com.wsh.sys.*;
import com.wsh.utils.FileUtil;
import com.wsh.utils.SecurityUtils;
import com.wsh.base.BaseVo;
import com.wsh.entity.sys.MenuEntity;
import com.wsh.entity.sys.UserEntity;
import com.wsh.mapper.sys.UserDao;
import com.wsh.utils.PageUtils;
import com.wsh.vo.sys.DepartmentTree;
import com.wsh.vo.sys.RePwdVo;
import com.wsh.vo.sys.UserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 王思涵
 * @Date 2019/7/20
 * @Version 1.0
 * @Desciption 用户业务接口实现类
 **/
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {

    /**
     * 附件业务
     */
    @Autowired
    private FileService fileService;

    /**
     * 菜单业务
     */
    @Autowired
    private MenuService menuService;

    /**
     * 权限业务
     */
    @Autowired
    private RoleMenuService roleMenuService;

    /**
     * 用户业务
     */
    @Autowired
    private RoleService roleService;

    /**
     * 部门业务
     */
    @Autowired
    private DepartmentService departmentService;

    @Override
    public void updateUserState(String userId) {
        UserEntity userEntity = findByUserName(userId, true);
        // 更新登陆时间
        userEntity.setUpdateTime(new Date());
        updateById(userEntity);
    }

    @Override
    public IPage<UserEntity> findListForPage(UserDto userDto) {
        // 分页数据处理
        IPage<UserEntity> pages = PageUtils.getPage(userDto);

        QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>()
                .orderByAsc("update_time");

        // 部门需要查询子节点
        String depId = userDto.getDepId();

        // 部门查询
        if (StringUtils.isNoneBlank(depId)) {
            List<DepartmentTree> departmentTrees = departmentService.departTree(depId);

            // 扁平化
            List<String> departmentArr =
                    departmentTrees.stream().flatMap(item -> item.getChildren().stream())
                    .map(DepartmentTree::getId).collect(Collectors.toList());
            departmentArr.add(depId);
            departmentTrees.stream().forEach(e -> departmentArr.add(e.getId()));

            queryWrapper.in("dep_id", departmentArr);
        }

        // 用户名
        String username = userDto.getUsername();
        queryWrapper.like(StringUtils.isNoneBlank(username), "username", username);

        // 真实姓名
        String realName = userDto.getRealName();
        queryWrapper.like(StringUtils.isNoneBlank(realName), "real_name", realName);

        // 所属角色
        String roleId = userDto.getRoleId();
        queryWrapper.eq(StringUtils.isNoneBlank(roleId), "role_id", roleId);

        // 分页查询处理
        IPage<UserEntity> page =  baseMapper.selectPage(pages, queryWrapper);

        return page;
    }

    @Override
    public UserEntity findUserByUsername(String username) {
        Map<String, Object> maps = new HashMap<>();
        maps.put("username", username);
        List<UserEntity> userEntities = baseMapper.selectByMap(maps);
        if (userEntities == null || userEntities.size() == 0) {
            return null;
        }
        return userEntities.get(0);
    }


    /**
     * 获取用户信息
     * @param userId
     * @param userInfo
     * @return
     */
    @Override
    public UserEntity findByUserName(String userId, boolean userInfo) {
        Map<String, Object> maps = new HashMap<>();
        maps.put("username", userId);
        List<UserEntity> userEntities = baseMapper.selectByMap(maps);
        if (userEntities.size() == 0) {
            return null;
        }

        UserEntity userEntity = userEntities.get(0);

        // 是否显示用户信息
        if (userInfo) {
            return userEntity;
        }

        // 头像
        List<Map<String, Object>> userFiles = fileService.getListByFormId(userEntity.getUserId(), true);
        if (userFiles != null && userFiles.size() > 0) {
            Map<String, Object> file = userFiles.get(0);
            userEntity.setAvatarImg((String)file.get("base64"));
        }


        // 用户名称
        String roleId = userEntity.getRoleId();
        String roleName = roleService.getById(roleId).getName();
        userEntity.setRoleName(roleName);

        // 部门名称
        String depId = userEntity.getDepId();
        String depName = departmentService.getById(depId).getName();
        userEntity.setDepName(depName);

        String[] menusArr = roleMenuService.getMenusByRole(roleId).getMenus();

        // 超级管理员时 查询全部
        if (Arrays.binarySearch(menusArr, "admin") > 0) {
            menusArr = null;
        }

        List<MenuEntity> menuInRouterGroupChildren = menuService.getMenuInRouterGroupChildren(menusArr);

        List<String> menus = menuInRouterGroupChildren.stream()
                .filter(e -> e.getRouterName() != null)
                .map(MenuEntity::getRouterName).collect(Collectors.toList());

        // 用户路由
        if (!SecurityUtils.isAdmin(roleId)) {
            userEntity.setMenus(menus.toArray(new String[menus.size()]));
        }

        // 用户菜单
        userEntity.setMenuEntityList(menuInRouterGroupChildren);

        return userEntity;
    }

    @Override
    public boolean rePwd(RePwdVo rePwdVo) throws Exception {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

        UserEntity userEntity = findByUserName(SecurityUtils.getUserDetails().getUsername(), true);

        String privateKey = rePwdVo.getPrivateKey();
        String beforePassword =  userEntity.getPassword();
        RSA rsa = new RSA(privateKey, null);
        String password = new String(rsa.decrypt(rePwdVo.getOldPwd(), KeyType.PrivateKey));

        if (!bCryptPasswordEncoder.matches(password, beforePassword)) {
            throw new Exception("原密码不正确");
        }

        String newPassword = rePwdVo.getPassword();

        if (rePwdVo.getRePassword().equals(newPassword)) {
            throw new Exception("俩次密码不同");
        }

        // 密码加密后更新密码
        userEntity.setPassword(bCryptPasswordEncoder.encode(new String(rsa.decrypt(newPassword, KeyType.PrivateKey))));

        return updateById(userEntity);
    }

    @Override
    public BaseVo<UserVo> findById(String formId) {
        UserEntity userEntity = getById(formId);
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(userEntity, userVo);
        return new BaseVo<>(userVo, fileService.getListByFormId(userVo.getUserId(), true));
    }

    @Override
    public boolean saveUser(UserVo userVo) {
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(userVo ,userEntity);
        if (StringUtils.isEmpty(userEntity.getUserId())) {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
            userEntity.setCreateTime(new Date());
            userEntity.setPassword(bCryptPasswordEncoder.encode("123456"));
        }

        userEntity.setUpdateTime(new Date());
        saveOrUpdate(userEntity);
        return fileService.uploadFormId(userVo.getNewFileList(), userVo.getFileRemoveIds(), userEntity.getUserId());
    }
}
